﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;

namespace CardLib
{
    public class Cards
    {
        protected List<Card> AllCards = new List<Card>();

        public Cards()
        {
        }

        public object Clone()
        {
            Cards newCards = new Cards();
            foreach (Card sourceCard in AllCards)
                newCards.Add(sourceCard.Clone() as Card);

            return newCards;
        }

        public void ShowCards()
        {
            for (int i = 0; i < AllCards.Count; i++)
            {
                Card tempCard = AllCards[i];
                if ((i + 1) % 13 == 0)
                    Console.Write(tempCard.ToString() + "\n");
                else
                    Console.Write(tempCard.ToString() + "\t");
            }
            Console.WriteLine("\n");
        }

        public int Count()
        {
            return AllCards.Count;
        }

        public Card GetCard(int cardIndex)
        {
            if (cardIndex >= 0 && cardIndex < AllCards.Count)
                return AllCards[cardIndex];
            else
                throw (new System.ArgumentOutOfRangeException("cardIndex", cardIndex, "Value out of range."));
        }

        public bool MoveTo(Card theCard, Cards targetCards)
        {
            Card tempCard = theCard;
            bool moved;
            moved = AllCards.Remove(theCard);
            if (moved)
                targetCards.Add(theCard);

            return moved;
        }

        public event ListChangedEventHandler OnChange;

        #region Hide some base methods

        public void Add(Card newCard)
        {
            AllCards.Add(newCard);
            if (OnChange != null)
            {
                ListChangedEventArgs e = new ListChangedEventArgs(ListChangedType.ItemAdded, 0);
                OnChange(newCard, e);
            }
        }

        public bool Remove(Card theCard)
        {
            bool Removed = false;
            Removed = AllCards.Remove(theCard);
            if (Removed)
            {
                if (OnChange != null)
                {
                    ListChangedEventArgs e = new ListChangedEventArgs(ListChangedType.ItemDeleted, 0);
                    OnChange(theCard, e);
                }
            }
            return Removed;
        }

        public void RemoveAt(int index)
        {
            AllCards.RemoveAt(index);
            if (OnChange != null)
            {
                ListChangedEventArgs e = new ListChangedEventArgs(ListChangedType.ItemDeleted, 0);
                OnChange(this, e);
            }
        }

        #endregion

        /// <summary>
        /// Sort cards by Rank as primary key, Suit as secondary key.
        /// </summary>
        public void Sort()
        {
            AllCards.Sort();

            List<Card> newCards = new List<Card>();
            List<Card> tempCards = new List<Card>();
            int UBound = 0;
            CardRank FirstRank = CardRank.Three;

            while (AllCards.Count() > 0)
            {
                UBound = 0;
                FirstRank = AllCards[0].Rank;

                for (int i = 1; i < AllCards.Count(); i++)
                {
                    if (AllCards[i].Rank != FirstRank)
                    {
                        UBound = i - 1;
                        break;
                    }
                    UBound = i;
                }

                tempCards.AddRange(AllCards.GetRange(0, UBound + 1));
                AllCards.RemoveRange(0, UBound + 1);

                tempCards.Sort(new SuitComparer());
                newCards.AddRange((List<Card>)tempCards);

                tempCards.Clear();
            }
            AllCards.AddRange(newCards);
        }
    }
}
